package geradordao;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.util.ArrayList;
import java.util.List;

public class TabelaSimbolos {

    private static List<Simbolo> simbolos = new ArrayList<Simbolo>();
    private Token token;

    public static void addSimbolo(Simbolo simbolo) {
        simbolos.add(simbolo);
    }

    public static void addSimbolo(Token token) {
        Simbolo simbolo = new Simbolo();
        simbolo.setToken(token);
        simbolos.add(simbolo);
    }

    public static void addSimbolo(Token token, String escopo, String classificacao) {
        for (Simbolo simbolo : simbolos) {
            if (simbolo.getToken().getImagem().equals(token.getImagem())) {
                if (simbolo.getEscopo().equalsIgnoreCase(escopo)) {
                    simbolo.setClassificacao(classificacao);
                    return;
                }
            }
        }

        Simbolo simbolo = new Simbolo();
        simbolo.setToken(token);
        simbolo.setClassificacao(classificacao);
        simbolos.add(simbolo);
    }

    public static List<Simbolo> getSimbolos() {
        return simbolos;
    }

    public static Simbolo getSimbolo(Token token) {
        for (Simbolo simbolo : simbolos) {
            if (simbolo.getToken().getImagem().equals(token.getImagem())) {
                return simbolo;
            }
        }
        return null;
    }

    public static Simbolo getSimbolo(String imagem) {
        for (Simbolo simbolo : simbolos) {
            if (simbolo.getToken().getImagem().equals(imagem)) {
                return simbolo;
            }
        }
        return null;
    }

    public static String getTipoSimbolo(Token token) {
        if (token.getClasse().equals("ID")) {
            Simbolo simbolo = getSimbolo(token);
            return simbolo.getTipo();
        } else {
            return getTipoEquiv(token.getClasse());
        }
    }

    public static void setTipoSimbolo(Token token, String tipo) {
        Simbolo simbolo = getSimbolo(token);
        String escopo = getEscopoSimbolo(token);
        if (simbolo == null) {
            throw new RuntimeException("Simbolo inexistente!");
        } else {
            for (Simbolo simbolo2 : simbolos) {
                if (simbolo2.getToken().equals(token) && simbolo2.getTipo() == null) {
                    simbolo2.setTipo(tipo);
                    if (escopo.equals(simbolo2.getToken().getImagem())) {
                        simbolo2.setEhEscopo(true);
                    }
                }
            }
        }
    }

    public static String getEscopoSimbolo(Token token) {
        if (token.getClasse().equals("ID")) {
            Simbolo simbolo = getSimbolo(token);
            return simbolo.getEscopo();
        } else {
            return getTipoEquiv(token.getClasse());
        }
    }

    public static List<Simbolo> getSimbolosByEscopo(String escopo) {

        List<Simbolo> simbolosByEscopo = new ArrayList<Simbolo>();
        for (Simbolo simb : simbolos) {
            if (simb.getEscopo().equals(escopo)) {
                simbolosByEscopo.add(simb);
            }
        }
        return simbolosByEscopo;
    }

    public static void setEscopoSimbolo(Token token, Token escopo) {
        if (token.getClasse().equals("ID")) {
            for (Simbolo simbolo : simbolos) {
                if (simbolo.getToken().equals(token) && simbolo.getEscopo() == null) {
                    simbolo.setEscopo(escopo);

                }
            }
        }
    }

    public static void setReferenciaSimbolo(String token, String referencia, Token escopo) {
        for (Simbolo simbolo : simbolos) {
            if (simbolo.getToken().getImagem().equals(token) && simbolo.getReferencia() == null && simbolo.getEscopo().equalsIgnoreCase(escopo.getImagem())) {
                simbolo.setReferencia(referencia);

            }
        }
    }

    public static List<Simbolo> getSimbolosChaveByEscopo(String escopo) {

        List<Simbolo> simbolosByEscopo = new ArrayList<Simbolo>();
        for (Simbolo simb : simbolos) {
            if (simb.getClassificacao().equalsIgnoreCase("foreing") && simb.getEscopo().equals(escopo)) {
                simbolosByEscopo.add(simb);
            }
        }
        return simbolosByEscopo;
    }

    public static List<Simbolo> getSimbolosAtribByEscopo(String escopo) {

        List<Simbolo> simbolosByEscopo = new ArrayList<Simbolo>();
        for (Simbolo simb : simbolos) {
            if (simb.getClassificacao().equalsIgnoreCase("atributo") && simb.getEscopo().equals(escopo)) {
                simbolosByEscopo.add(simb);
            }
        }
        return simbolosByEscopo;
    }

    public static boolean ehReferencia(String referencia) {
        for (Simbolo simbolo : simbolos) {
            if ((simbolo.getReferencia() != null) && (simbolo.getReferencia().equalsIgnoreCase(referencia))) {
                return true;
            }
        }
        return false;
    }

    public static boolean ehAtributo(Token simb) {
        for (Simbolo simbolo : simbolos) {
            if (((simbolo.getClassificacao().equalsIgnoreCase("atributo")) && (simbolo.getToken().equals(simb)))
                    || (simbolo.getClassificacao().equalsIgnoreCase("primary")) && (simbolo.getToken().equals(simb))) {
                return true;
            }
        }
        return false;
    }

    public static List<String> getClassePorReferencia(String referencia) {
        List<String> referencias = new ArrayList<String>();
        for (Simbolo simbolo : simbolos) {
            if ((simbolo.getReferencia() != null) && (simbolo.getReferencia().equals(referencia))) {
                referencias.add(simbolo.getEscopo());
            }
        }
        return referencias;
    }

    public static boolean ehEscopo(Token token) {
        for (Simbolo simbolo : simbolos) {
            return simbolo.getEhEscopo();
        }
        return false;
    }

    public static void mostraSimbolos() {
        int i = 0;
        for (Simbolo simbolo : simbolos) {
            if (simbolo.getTipo() != null) {
                i++;
                System.out.println("Simbolo: " + i + ": " + simbolo);
            }
        }
    }

    public static Token getToken(Token token) {
        return token;
    }

    public void setToken(Token token, String tipo) {
        this.token = token;
    }

    public static String getTipoEquiv(String classe) {
        if (classe.equals("CLI")) {
            return "int";
        }
        if (classe.equals("CLR")) {
            return "real";
        }
        if (classe.equals("CLS")) {
            return "str";
        }
        return null;
    }

    /**
     * <Tipo> ::= 'inteiro' | 'real' | 'string'
     */
    public static String getTipoCompativelASM(String tipo) {
        if (tipo.equals("int")) {
            return "DD";
        } else if (tipo.equals("real")) {
            return "DD";
        } else if (tipo.equals("str")) {
            return "DB";
        }
        throw new RuntimeException("Tipo não existente!");
    }

    /**
     * <Type>  ::=  bit  | date  |  time | timestamp |  decimal  |  real |  float
    |  smallint |  integer | int  |  interval |  character |  varchar <Tamanho>
     */
    public static String getTipoJavaEquivalente(String tipoSQL) {
        if (tipoSQL.equals("bit") || tipoSQL.equals("smallint") || tipoSQL.equals("integer") || tipoSQL.equals("int")) {
            return "Integer";
        } else if (tipoSQL.equals("date") || tipoSQL.equals("time") || tipoSQL.equals("timestamp") || tipoSQL.equals("interval")) {
            return "Date";
        } else if (tipoSQL.equals("decimal") || tipoSQL.equals("real") || tipoSQL.equals("float") || tipoSQL.equals("double")) {
            return "Double";
        } else if (tipoSQL.equals("character") || tipoSQL.equals("varchar")) {
            return "String";
        }
        return null;
    }
}
